using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using UCS.XNA.Draughts.Boards;
using UCS.XNA.Draughts.Squares;
using UCS.XNA.Utils;
using UCS.XNA.Utils.Animation;
using UCS.XNA.Utils.Geometries;

namespace UCS.XNA.Draughts.Pieces
{
    public abstract class Piece : ITranslateAnimatable, ICircle
    {
        #region Constants

        private const int WIDTH = 44;
        private const int HEIGHT = 44;

        #endregion

        #region Attributes and Properties

        protected List<PieceMovement> _movements;
        public List<PieceMovement> Movements
        {
            get { return this._movements; }
        }

        protected BoardPosition _boardPosition;
        public BoardPosition BoardPosition
        {
            get { return this._boardPosition; }
            set
            {
                this._boardPosition = value;

                this.ResetPositionUsingAnimation();
            }
        }

        protected Vector2 _position;
        public Vector2 Position
        {
            get { return this._position; }
            set
            {
                this._position = value;

                if (this._position != null)
                    this._bounds = new Rectangle(Convert.ToInt32(this._position.X), Convert.ToInt32(this._position.Y), WIDTH, HEIGHT);
            }
        }

        protected PieceColor _color;
        public PieceColor Color
        {
            get { return this._color; }
        }

        public float Radius
        {
            get { return WIDTH / 2; }
        }

        public float Scale
        {
            get { return 1f; }
            set { }
        }

        public float X
        {
            get { return _position.X + Radius; }
        }

        public float Y
        {
            get { return _position.Y + Radius; }
        }

        public Vector2 Direction
        {
            get { return Vector2.Zero; }
            set { }
        }

        public float SpeedFactor
        {
            get { return 1f; }
            set { }
        }

        private bool _isBeingDragged = false;
        public bool IsBeingDragged
        {
            get { return _isBeingDragged; }
            set
            {
                _isBeingDragged = value;

                if (_isBeingDragged == false)
                    this.ResetPositionUsingAnimation();
            }
        }

        #endregion

        #region Private Members

        private TranslateAnimation _translateAnimation;

        #endregion

        #region Protected Members

        protected Texture2D _texture;
        protected Rectangle _bounds;

        #endregion

        #region Events

        public event EventHandler AnimationEnded;

        #endregion

        #region Constructors

        protected Piece(PieceColor color, BoardPosition boardPosition)
        {
            this._color = color;
            this._boardPosition = boardPosition;

            this.ResetPosition();
        }

        protected Piece(Piece piece)
        {
            _boardPosition = piece.BoardPosition.Clone();
            _position = new Vector2(piece.Position.X, piece.Position.Y);
            _color = piece.Color;
        }

        #endregion

        #region Private Methods

        private void ResetPosition()
        {
            this.Position = new Vector2(this._boardPosition.J * 58 + 8, this._boardPosition.I * 58 + 8);
        }

        #endregion

        #region Public Methods

        public void Update(GameTime gameTime)
        {
            if (this._translateAnimation != null)
                this._translateAnimation.Update(gameTime);
        }

        public void Draw(GameTime gameTime)
        {
            GameResources.SpriteBatch.Draw(this._texture, this._position, null, Microsoft.Xna.Framework.Color.White, 0, Vector2.Zero, 1, SpriteEffects.None, this._isBeingDragged || this._translateAnimation != null? 0.1f : 0.3f);
        }

        public void ResetPositionUsingAnimation()
        {
            this._translateAnimation = new TranslateAnimation(this, new Vector2(this._boardPosition.J * 58 + 8, this._boardPosition.I * 58 + 8), 5);
            this._translateAnimation.AnimationFinished += (sender, e) =>
            {
                this._translateAnimation = null;
                if (this.AnimationEnded != null)
                    this.AnimationEnded(this, new EventArgs());
            };
        }

        public PieceMovement GetMovement(BoardPosition resultPosition)
        {
            BoardPosition movementOffset = resultPosition - _boardPosition;
            foreach (PieceMovement movement in this.Movements)
            {
                if (movementOffset.Equals(movement.BoardMovement))
                    return movement;
            }

            return null;
        }

        #endregion

        #region Abstract Methods

        public abstract void InitializeTextures();
        public abstract Piece Clone();

        #endregion
    }
}
